﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Epam.Exceptions.RepositoryExceptions;
using Epam.PeopleInterfaces;

namespace Epam.PeopleRepository
{
    public class PeopleSqlRepository:CrossEntityRepository,IPeopleRepository
    {
        
        public void Create(IPeopleEntity item)
        {
            try
            {
                Peoples.Add(FromBusinessToDtoMapper.Convert(item));
                SaveChanges();
            }
            catch (Exception e)
            {
                throw new CrudOperationException("Create operation failed. " + e.Message);
            } 
          
        }

        public void Update(IPeopleEntity item)
        {
            try
            {
                DtoPeopleEntity temp =
               (from dtoPeopleEntity in Peoples where dtoPeopleEntity.Id == item.Id select dtoPeopleEntity).
                   FirstOrDefault();
                if (temp != null)
                {
                    temp.Name = item.Name;
                    temp.BirthDate = item.BirthDate;
                    temp.Weight = item.Weight;
                    temp.Height = item.Height;
                }
                SaveChanges();
            }
            catch (Exception e)
            {
                throw new CrudOperationException("Update operation failed. " + e.Message);
            } 

        }

        public void Delete(Guid id)
        {
            try
            {
                DtoPeopleEntity temp =
               (from dtoPeopleEntity in Peoples where dtoPeopleEntity.Id == id select dtoPeopleEntity).
                   FirstOrDefault();
                if (temp != null)
                {
                    Peoples.Remove(temp);
                    SaveChanges();
                }
            }
            catch (Exception e)
            {
                throw new CrudOperationException("Delete operation failed. " + e.Message);
            }
          
        }

        public IDtoPeopleEntity GetById(Guid id)
        {
            try
            {
                return (from dtoPeopleEntity in Peoples
                        where
                            dtoPeopleEntity.Id == id
                        select
                            dtoPeopleEntity).FirstOrDefault();
            }
            catch (Exception e)
            {
                throw new FindOperationException("GetById operation failed. " + e.Message);
            }
           
        }

        public IEnumerable<IDtoPeopleEntity> ReadAll()
        {
            try
            {
                return Peoples.ToList();
            }
            catch (Exception e)
            {
                throw new FindOperationException("ReadAll operation failed. " + e.Message);
            }
            
        }

        public IEnumerable<IDtoPeopleEntity> ReadPage(int currentPage, int itemPerPage)
        {
            try
            {
                if (currentPage < 0 || itemPerPage <= 0) return new Collection<IDtoPeopleEntity>();
                return Peoples.OrderBy(item => item.BirthDate).Skip(currentPage * itemPerPage).Take(itemPerPage);
            }
            catch (Exception e)
            {
                throw new FindOperationException("ReadPage operation failed. " + e.Message);
            }
           
        }

        public IEnumerable<IDtoPeopleEntity> Filter(double lowfactor, double hightfactor, IFilterAlgoritm filter)
        {
            try
            {
                return (from dtoPeopleEntity in Peoples.ToList()
                        where filter.FiltrateByFactor(dtoPeopleEntity.Weight, dtoPeopleEntity.Height) >= lowfactor
                              && filter.FiltrateByFactor(dtoPeopleEntity.Weight, dtoPeopleEntity.Height) < hightfactor
                        select dtoPeopleEntity).OrderBy(ent => ent.BirthDate);
            }
            catch (Exception e)
            {
                throw new FindOperationException("Filter operation failed. "+e.Message);
            }
           

        }
    }
}
